<template>
  <div class="calendar">
    <div class="select flex items-center justify-between flex-wrap">
      <div class="flex items-center">
        <div class="year-month"> {{ curYear }} 年 {{ curMonth + 1 }} 月</div>
        <d-button class="quick-btn" @click="handleQuickChange('prev')" >
          <GIcon name="gt-line-down" size="18px" rotate="90deg" />
        </d-button>
        <d-button class="quick-btn" @click="handleQuickChange('next')">
          <GIcon name="gt-line-down" size="18px"  rotate="-90deg" />
        </d-button>
        <d-button  class="ml-[16px]" @click="handleToday">{{ t('activity.viewToday') }}</d-button>
      </div>
      <slot name="checkbox"/>
    </div>

    <table class="calendar-table" :style="{width}">
      <thead>
        <tr class="week-header">
          <th v-for="(item, i) in weeks" :key="i">{{ item }}</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(dates, i) in res" :key="i" :style="{height: tbodyHeight}">
          <td
            v-for="(item, index) in dates"
            class="calendar-cell"
            :key="index"
            :class="{
              notCurMonth: !item.isCurMonth, 
              selectDay: item.isSelected || (item.date === curDate && (!selectedDates.length || selectedDates.includes(item.date))), 
              rangeSelectd: item.isRangeSelected, 
              weekend: item.isWeekend,
              phone: isPhone()
            }"
            @click.stop="handleItemClick(item, i, index)"
            @mouseover="handleItemMove(item, i, index)"
          >
            <!-- <div v-if="!item.data || item.data?.length === 0" class="calendar-cell-empty">
              <GIcon name="gt-plane-add" size="21px" />
              <p v-if="!isPhone()">{{ t('activity.createActivity') }}</p>
            </div> -->
          <!-- pc端 -->
           <ClientOnly v-if="!isPhone()">
            <d-popover v-if="item.data.length > 0" :position="['bottom']" trigger="hover"  class="calendar-popover" :offset="{
              mainAxis: -50,
            }">
              <div class="calendar-cell-content">
                <div class="date"> {{ item.day }}</div>
                <div class="item-content">
                  <template v-for="(d, index) in item.data" :key="d.id">
                    <p v-if="index < 3" class="item-content-title">
                      <span class="points" :style="{backgroundColor:  pointsColor(d.liveBroadcast)}"></span>
                      {{ d.title }}
                    </p>
                  </template>
                  
                </div>
                <div v-if="item.data.length > 4" class="more-btn">
                  <span>More</span> + {{ item.data.length  - 3 }}
                </div>
              </div>
              <template #content>
                <div class="popover-content">
                  <GLink class="popover-content-title" target="_blank" :href="'/activity/' + item.data[item.currentIndex].id ">{{ item.data[item.currentIndex].title }}</GLink>
                  <p class="popover-content-time">
                    <span class="label">时间：</span>
                    <span> {{ item.data[item.currentIndex].startTime }} 至 {{ item.data[item.currentIndex].endTime }}</span>
                  </p>
                  <p v-if="item.data[item.currentIndex].hostProvince && item.data[item.currentIndex].hostCity" class="popover-content-address">
                    <span class="label">地址：</span>
                    <span>{{ item.data[item.currentIndex].hostProvince }} {{ item.data[item.currentIndex].hostCity }}</span>
                  </p>
                  <div v-if="item.data.length > 1" class="btn-group">
                    <GIcon name="gt-line-down" size="18px" rotate="90deg" @click="handleMore(item, 'prev')" />
                    <GIcon name="gt-line-down" size="18px"  rotate="-90deg" @click="handleMore(item, 'next')" />
                  </div>
                </div>
              </template>
            </d-popover>
            <div v-else class="calendar-cell-content">
              <div class="date"> {{ item.day }}</div>
              <div class="item-content">
                <p v-for="d in item.data" class="item-content-title">
                  <span class="points" :style="{backgroundColor:  pointsColor(d.liveBroadcast)}"></span>
                  {{ d.title }}
                </p>
              </div>
              <div v-if="item.data.length > 4" class="more-btn">
                <span>More</span> + {{ item.data.length  - 3}}
              </div>
            </div>
           </ClientOnly>
           <!-- 手机端 -->
           <ClientOnly v-else>
            <div class="calendar-cell-content">
                <div class="date"> {{ item.day }}</div>
                <div class="item-content">
                  <template v-for="(d, index) in item.data" :key="d.id">
                    <p v-if="index < 3" class="item-content-title">
                      <span class="points" :style="{
                        backgroundColor: pointsColor(d.liveBroadcast)
                      }">
                      </span>
                      <!-- {{ d.title }} -->
                    </p>
                  </template>
                  
                </div>
                <div v-if="item.data.length > 4" class="more-btn">
                 +{{ item.data.length }}
                </div>
              </div>
           </ClientOnly>
          </td>
        </tr>
      </tbody>
    </table>
    <div class="calendar-details" v-if="selectedDates.length > 0 && isPhone()">
      <p class="details-title"> {{ selectedDatesDetails.date }}</p>
      <div class="item-content">
        <p v-for="(d, index) in selectedDatesDetails.data" :key="d.id" class="item-content-title">
          <span class="points" :style="{backgroundColor:  pointsColor(d.liveBroadcast)}"></span>
          <GLink :href="`/activity/${d.id}`" target="_blank">{{ d.title }}</GLink>
        </p>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted, defineExpose } from 'vue'
import { getDaysInMonth, handleCrateDate, handleCreateDatePicker, parseTime, isDateInRange } from './utils'
import isPhone from '@/utils/isPhone';
import { useI18n } from 'vue-i18n';

// Props
const props = defineProps({
  selectMode: {
    type: String,
    default: 'click'
  },
  chooseDate: {
    type: String,
    default: ''
  },
  startOfWeek: {
    type: Number,
    default: 1
  },
  canSelect: {
    type: Boolean,
    default: true
  },
  width: {
    type: String,
    default: '100%'
  },
  tbodyHeight: {
    type: String,
    default: '60px'
  },
  dataList: {
    type: Array,
    default: []
  },
  allDataList: {
    type: Array,
    default: []
  }
})

// Emits
const emit = defineEmits(['dateSelected', 'currentMonth']);

const { t } = useI18n();

// Reactive state
const monthOptions = ref([])
const yearOptions = ref([])
const weeks = ref([t('activity.monday'), t('activity.tuesday'), t('activity.wednesday'), t('activity.thursday'), t('activity.friday'), t('activity.saturday'), t('activity.sunday')])
const curYear = ref(new Date().getFullYear())
const curMonth = ref(new Date().getMonth())
const days = ref(0)
const curDate = ref(parseTime(new Date().getTime()))
const prevDays = ref([])
const rearDays = ref([])
const curDays = ref([])
const showDays = ref([])
const res = ref([])
const selectedDates = ref([])
const selectedMode = ref(props.selectMode === 'click')
const moveIndex = ref([])
const canMove = ref(false);
const selectedDatesDetails = ref(null);
const isClearSelectedDates = ref(true);

// 获取当月视图所有日期
const handleGetDays = (year, month) => {
  showDays.value = []
  days.value = getDaysInMonth(year, month)
  let firstDayOfWeek = new Date(year, month, 1).getDay();
  const obj = {
    1: '星期一', 2: '星期二', 3: '星期三', 4: '星期四', 5: '星期五', 6: '星期六', 0: '星期日'
  }
  const firstDayInCN = obj[firstDayOfWeek]
  const index = weeks.value.indexOf(firstDayInCN)

  prevDays.value = handleCrateDate(year, month, 1, index + 1, 'prev', props.dataList)
  rearDays.value = handleCrateDate(year, month, 1, 42 - days.value - (index), 'rear', props.dataList)
  curDays.value = handleCrateDate(year, month, 1, days.value, '', props.dataList)
  showDays.value = [...prevDays.value, ...curDays.value, ...rearDays.value]
  res.value = handleFormatDates(showDays.value);
}

const handleFormatDates = (arr, size = 7) => {
  const arr2 = []
  for (let i = 0; i < 6; i++) {
    const temp = arr.slice(i * size, i * size + size)
    arr2.push(temp)
  }
  return arr2
}
const pointsColor = (liveBroadcast) => {
  switch (liveBroadcast) {
    case '线上直播':
      return '#2951E0'
    case '线下沙龙':
      return '#088F4E'
    case '创新大赛':
      return '#8A25D9'
    default:
      return '#ED5F22'
  }
}

const handleMore = (item, type) => {
  if (type === 'prev') {
    if (item.currentIndex > 0) {
      item.currentIndex--
     }
  } else {
    if (item.currentIndex < item.data.length - 1) {
      item.currentIndex++
    }
  }
}

const clearSelectedDates = () => {
  selectedDates.value = []
  res.value.forEach(item => {
    item.forEach(item2 => {
      item2.isSelected = false
      item2.isRangeSelected = false
    })
  })
}

const handleItemClick = (item, i, j) => {
  if (!props.canSelect) return
  clearSelectedDates()
  if (item.data.length === 0) {
      return
    }
  if (selectedMode.value) {
    res.value[i][j].isSelected = !res.value[i][j].isSelected
    if (res.value[i][j].isSelected) {
      selectedDates.value.push(res.value[i][j].date)
      selectedDates.value = Array.from(new Set(selectedDates.value))
    } else {
      selectedDates.value.splice(selectedDates.value.indexOf(item.date), 1)
    }
    selectedDatesDetails.value = Object.assign({}, item, {week: weeks.value[j]});
    if (!isPhone()) {
      emit('dateSelected', selectedDatesDetails.value)
    }
  } else {
    const index = i * 7 + j
    canMove.value = true
    if (moveIndex.value.length === 1) {
      canMove.value = false
    }
    if (moveIndex.value.length === 2) {
      showDays.value.forEach(item => {
        item.isSelected = false
        item.isRangeSelected = false
      })
      canMove.value = true
      moveIndex.value = []
    }
    moveIndex.value.push(index)
    moveIndex.value.sort((a, b) => a - b)
    selectedDates.value = showDays.value.slice(moveIndex.value[0], moveIndex.value[1] + 1)
    selectedDates.value.length !== 0 && emit('dateSelected', selectedDates.value)
  }
}

const handleItemMove = (data, i, j) => {
  if (canMove.value && !selectedMode.value) {
    const index = i * 7 + j
    showDays.value.forEach(item => {
      item.isSelected = false
      item.isRangeSelected = false
    })
    showDays.value[index].isSelected = true
    showDays.value[moveIndex.value[0]].isSelected = true

    if (moveIndex.value[0] < index) {
      for (let i = moveIndex.value[0] + 1; i < index; i++) {
        showDays.value[i].isRangeSelected = true
      }
    } else {
      for (let i = index + 1; i < moveIndex.value[0]; i++) {
        showDays.value[i].isRangeSelected = true
      }
    }
  }
}
// 上个月，下个月
const handleQuickChange = (type) => {
  if (type === 'prev') {
    curMonth.value--
    if (curMonth.value === -1) {
      curMonth.value = 11
      curYear.value -= 1
    }
  } else if (type === 'next') {
    curMonth.value++
    if (curMonth.value === 12) {
      curMonth.value = 0
      curYear.value += 1
    }
  }
  handleGetDays(curYear.value, curMonth.value)
  emit('currentMonth', new Date(curYear.value, curMonth.value))
}
const handleToday = () => {
  curYear.value = new Date().getFullYear()
  curMonth.value = new Date().getMonth()
  const today = {
    date: parseTime(new Date()),
    day: new Date().getDay().toString().padStart(2, '0'),
    isCurMonth: true,
    isSelected: false,
    isRangeSelected: false,
    currentIndex: 0,
    data: props.allDataList?.filter((item) => {
      return isDateInRange(item.startTime, item.endTime, new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate()).getTime())
    })
  }
 
  handleGetDays(curYear.value, curMonth.value)
  emit('currentMonth', new Date(curYear.value, curMonth.value))
  emit('dateSelected', today)
  selectedDates.value = [today.date]
  selectedDatesDetails.value = today;
  if (isPhone()) {
    isClearSelectedDates.value = false;
  }
}
// watch(() => props.chooseDate, () => {
//   const date = new Date(props.chooseDate)
//   curYear.value = date.getFullYear()
//   curMonth.value = date.getMonth()
//   handleGetDays(curYear.value, curMonth.value)
// })

// Watchers

watch(() => props.dataList, () => {
  handleGetDays(curYear.value, curMonth.value);
  if (isClearSelectedDates.value) {
    selectedDates.value = [];
  }
})
const changeSelectDate = (types) => {
  if (selectedDatesDetails.value && isPhone()) {
    selectedDatesDetails.value.data?.forEach((item: { liveBroadcast: string; }) => {
      item.show = !item.liveBroadcast || types.includes(item.liveBroadcast);
    })
  }
}

// Lifecycle hooks
weeks.value.unshift(...weeks.value.splice(props.startOfWeek - 1))
handleGetDays(curYear.value, curMonth.value)
onMounted(() => {
  const datePicker = handleCreateDatePicker()
  monthOptions.value = datePicker.months
  yearOptions.value = datePicker.years
  if (localStorage.selectedDates) {
    selectedDates.value = JSON.parse(localStorage.selectedDates)
  }
})
const changeMonth = (year, month) => {
  curYear.value = year
  curMonth.value = month
  handleGetDays(year, month)
}
defineExpose({
  changeMonth,
  changeSelectDate
})
</script>

<style scoped lang="scss">
.select{
  display: flex;
  align-items: center;
  gap: 10px;
}
.quick-btn{
  padding: 0;
  border: none;
  margin-left: 16px;
  background-color: transparent;
}
.calendar-details{
  margin-top: 16px;
  margin-bottom: 16px;
  padding: 16px;
  border: 1px solid $devui-dividing-line;
  .details-title{
    font-size: 18px;
    font-weight: bold;
    margin-bottom: 16px;
  }
}
.calendar-cell{
  min-width: 105px;
  max-width: 172px;
  height: 172px;
  vertical-align: top;
  cursor: pointer;
  border: 1px solid $devui-dividing-line;
  position: relative;
  .calendar-cell-empty{
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    p {
      margin-top: 32px;
      white-space: nowrap;
    }
  }
  &.phone{
    min-width: 50px;
    max-width: 172px;
    height: 70px;
    .calendar-cell-content{
      padding: 5px;
    }
    .calendar-cell-empty{
      top: 70%;
    }
    .item-content{
      display: flex;
      align-items: center;
      justify-content: space-around;
      margin-top: 0px;
      .item-content-title {
       line-height: 6px;
      }
    }
    .item-content {
      margin: 0;
    }
    .more-btn{
      margin: 0;
    }
  }
  .calendar-cell-content{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    padding: 10px 8px;
    border: 2px solid transparent;
    &:hover{
      border: 2px solid $devui-brand;
    }
  }
  .date {
    text-align: right;
    font-size: 16px;
    font-weight: 600;
  }


}
.item-content{
    overflow: hidden;
    text-overflow: ellipsis;
    margin-top: 18px;
    .item-content-title{
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      vertical-align: middle;
      margin-bottom: 6px;
     
    }
  }
.points{
  width: 6px;
  height: 6px;
  display: inline-block;
  border-radius: 50%;
  vertical-align: middle;
  margin-right: 5px;
}
.week-header{
  background-color: $devui-feedback-overlay-bg;
  color: $devui-light-text;
  border: 1px solid $devui-feedback-overlay-bg;
  th{
    border: 1px solid $devui-feedback-overlay-bg;
  }
}
.year-month{
  font-size: 20px;
  font-weight: 600;
}
.calendar-table{
  table-layout: fixed;
  border-collapse: collapse;
  margin-top: 16px;
  transition: .3s;
  thead tr{
    height: 50px;
  }

}

.notCurMonth{
  color: #C0C4CC;
}
.selectDay{
  /* border: 1px solid $devui-brand !important; */
  .calendar-cell-content{
    border: 2px solid $devui-brand !important;
  }
}
.rangeSelectd{
  color: #606266;
  background-color: #dee2e9;
}
.more-btn{
  color: var(--devui-link);
  cursor: pointer;
  margin-top: 8px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.weekend{
  color: #F73131;
}
</style>
<style lang="scss">
.calendar-popover{
  background-color: var(--devui-connected-overlay-b) !important;
  color: var(--devui-text-color) !important;
  .devui-flexible-overlay__arrow{
    display: none !important;
  }
  .popover-content{
    padding: 16px;
    width: 300px;
    /* height: 188px; */
    .popover-content-title{
      font-size: 16px;
      font-weight: 600;
      color: var(--devui-link);
      white-space: wrap;
      /* 两行超出省略号 */
      display: -webkit-box;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
      overflow: hidden;
      cursor: pointer;
      /* 鼠标悬停有下划线 */
      &:hover{
        text-decoration: underline;
      }
    }
    .label{
      color: var(--devui-placeholder);
    }
    .popover-content-time{
      margin: 16px 0;
    }
    .popover-content-address{
      margin-bottom: 16px;
    }
    .btn-group{
      display: flex;
      align-items: center;
      justify-content: flex-end;
      gap: 10px;
      color: var(--devui-aide-text);
      cursor: pointer;
    }
  }
}
</style>